package ConnectivityEditor.Window; import java.util.ArrayList; import Common.Matrix4; import Common.Vector3f; import Connectivity.CollisionBox; import LDraw.Files.LDrawModel; import LDraw.Support.MatrixMath; import LDraw.Support.PartLibrary; import Renderer.ILDrawCollector; import Renderer.LDrawTextureSpec; public class CollisionBoxGenerator implements ILDrawCollector { private static CollisionBoxGenerator _instance = null; private CollisionBoxGenerator() { quad = new ArrayList<Vector3f>(); tri = new ArrayList<Vector3f>(); } public static synchronized CollisionBoxGenerator getInstance() { if (_instance == null) _instance = new CollisionBoxGenerator(); return _instance; } private ArrayList<Vector3f> quad = null; private ArrayList<Vector3f> tri = null; public ArrayList<CollisionBox> generateCollisionBox(String partName) { quad.clear(); tri.clear(); ArrayList<CollisionBox> retList = new ArrayList<CollisionBox>(); LDrawModel model = PartLibrary.sharedPartLibrary().modelForName( partName); if (model != null) model.collectSelf(this); for (int i = 0; i < quad.size(); i += 4) { Vector3f vertices[] = new Vector3f[4]; for (int j = 0; j < 4; j++) vertices[j] = quad.get(i + j); CollisionBox cb = getCollisionBox(vertices); if (cb == null) continue; retList.add(cb); } return retList; } public CollisionBox getCollisionBox(Vector3f[] vertices) { Vector3f edge[] = new Vector3f[4]; float[] edgeLength = new float[4]; for (int k = 0; k < 4; k++) { edge[k] = vertices[(k + 1) % 4].sub(vertices[k]); edgeLength[k] = edge[k].length(); } boolean isTooSmall = true; for (int k = 0; k < 2; k++) if (edgeLength[k] >= 5) isTooSmall = false; if (isTooSmall) return null; if (MatrixMath.compareFloat(edge[0].dot(edge[1]), 0) != 0 || MatrixMath.compareFloat(edge[1].dot(edge[2]), 0) != 0) { // ���� �� ���� �. int longestEdgeIndex = 0; float longestEdgeLength = -1; for (int i = 0; i < 4; i++) if (edgeLength[i] > longestEdgeLength) { longestEdgeLength = edgeLength[i]; longestEdgeIndex = i; } float offset0 = -edge[(longestEdgeIndex + 3) % 4] .dot(edge[longestEdgeIndex]) / edgeLength[longestEdgeIndex]; float offset1 = edge[(longestEdgeIndex + 1) % 4] .dot(edge[longestEdgeIndex]) / edgeLength[longestEdgeIndex]; if (offset0 > 0) vertices[longestEdgeIndex] = vertices[longestEdgeIndex] .add(MatrixMath.V3Normalize(edge[longestEdgeIndex]) .scale(offset0)); else vertices[(longestEdgeIndex + 3) % 4] = vertices[(longestEdgeIndex + 3) % 4] .add(MatrixMath.V3Normalize(edge[longestEdgeIndex]) .scale(-offset0)); if (offset1 < 0) vertices[(longestEdgeIndex + 1) % 4] = vertices[(longestEdgeIndex + 1) % 4] .add(MatrixMath.V3Normalize(edge[longestEdgeIndex]) .scale(offset1)); else vertices[(longestEdgeIndex + 2) % 4] = vertices[(longestEdgeIndex + 2) % 4] .add(MatrixMath.V3Normalize(edge[longestEdgeIndex]) .scale(-offset1)); for (int k = 0; k < 4; k++) { edge[k] = vertices[(k + 1) % 4].sub(vertices[k]); edgeLength[k] = edge[k].length(); } if (MatrixMath.compareFloat(edgeLength[(longestEdgeIndex + 3) % 4], edgeLength[(longestEdgeIndex + 1) % 4]) != 0) { if (edgeLength[(longestEdgeIndex + 3) % 4] < edgeLength[(longestEdgeIndex + 1) % 4]) { vertices[(longestEdgeIndex + 2) % 4] = vertices[(longestEdgeIndex + 3) % 4] .add(edge[longestEdgeIndex]); } else vertices[(longestEdgeIndex + 3) % 4] = vertices[(longestEdgeIndex + 2) % 4] .sub(edge[longestEdgeIndex]); } } Vector3f initialNormalVector = new Vector3f(0, 0, 1); Vector3f finalNormalVector = MatrixMath.V3Cross( MatrixMath.V3Sub(vertices[1], vertices[0]), MatrixMath.V3Sub(vertices[3], vertices[0])); finalNormalVector.normalize(); Vector3f rotationVector = initialNormalVector.cross(finalNormalVector); float rotationDegree = (float) Math .acos(initialNormalVector.dot(finalNormalVector) / (initialNormalVector.length() * initialNormalVector .length())); if (Float.isNaN(rotationDegree)) rotationDegree = 0; if (rotationVector.equals(Vector3f.getZeroVector3f())) rotationDegree = 0; Matrix4 testMatrix = Matrix4.getIdentityMatrix4(); if (rotationDegree != 0) testMatrix.rotate(-rotationDegree, rotationVector); else if (finalNormalVector.equals(testMatrix .transformPoint(initialNormalVector)) == false) { // System.out.println(finalNormalVector+" : "+testMatrix // .transformPoint(initialNormalVector)); testMatrix.rotate((float) Math.PI, new Vector3f(1, 0, 0)); } if (finalNormalVector.equals(testMatrix .transformPoint(initialNormalVector)) == false) { System.out.println("Fist Rotation: " + testMatrix.transformPoint(initialNormalVector) + " : " + finalNormalVector); return null; } Vector3f unitDirectionVector2 = new Vector3f(0, 1, 0); Vector3f finalDirectionVector2 = vertices[2].sub(vertices[1]); finalDirectionVector2.normalize(); Vector3f transformedUnit = testMatrix .transformPoint(unitDirectionVector2); if (transformedUnit.equals(finalDirectionVector2.scale(-1))) { testMatrix.rotate((float) Math.PI, finalNormalVector); } Vector3f rotationVector2 = transformedUnit.cross(finalDirectionVector2); rotationVector2.normalize(); // if(rotationVector2.equals(finalNormalVector)==false){ // System.out.println("asdf"); // } float rotationDegree2 = (float) Math.acos(testMatrix.transformPoint( unitDirectionVector2).dot(finalDirectionVector2) / (finalDirectionVector2.length() * finalDirectionVector2 .length())); if (Float.isNaN(rotationDegree2)) rotationDegree2 = 0; if (rotationVector2.equals(Vector3f.getZeroVector3f())) rotationDegree2 = 0; // System.out.println("##################################"); // System.out.println(testMatrix.transformPoint(initialNormalVector) + // " : " // + finalNormalVector + ":: " + // rotationVector2+"("+rotationDegree2+")"); if (rotationDegree2 != 0) testMatrix.rotate(-rotationDegree2, rotationVector2); else if (finalDirectionVector2.equals(testMatrix .transformPoint(unitDirectionVector2)) == false) { System.out.println(finalDirectionVector2 + " : " + testMatrix.transformPoint(unitDirectionVector2)); // testMatrix.rotate((float) Math.PI, new Vector3f(1, 0, 0)); } // if (finalNormalVector.equals(testMatrix .transformPoint(initialNormalVector)) == false) { System.out.println("Second Rotation_1: " + testMatrix.transformPoint(initialNormalVector) + " : " + finalNormalVector + ":: " + rotationVector2 + "(" + rotationDegree2 + ")"); // for(int i=0; i < 4; i++) // System.out.println(vertices[i]); return null; } // if (finalDirectionVector2.equals(testMatrix .transformPoint(unitDirectionVector2)) == false) { System.out.println("Second Rotation_2: " + testMatrix.transformPoint(unitDirectionVector2) + " : " + finalDirectionVector2 + ":: " + rotationDegree2); return null; } Vector3f normalVector = MatrixMath.V3Cross( MatrixMath.V3Sub(vertices[1], vertices[0]), MatrixMath.V3Sub(vertices[3], vertices[0])); normalVector.normalize(); for (int k = 0; k < 4; k++) { vertices[k] = vertices[k].sub(normalVector.scale(0.1f)); } // for (int k = 0; k < 4; k++) { edge[k] = vertices[(k + 1) % 4].sub(vertices[k]); edgeLength[k] = edge[k].length(); } // System.out.println(rotationVector+" : "+rotationVector2); Vector3f size = new Vector3f(edgeLength[0], edgeLength[1], 0) .scale(0.49f); Vector3f center = vertices[0].add(vertices[2]).scale(0.5f); CollisionBox cb = new CollisionBox(); cb.setSize(size.x, size.y, size.z); cb.setTransformMatrix(testMatrix); cb.moveTo(center); cb.setFileName("Collision Box"); cb.updateConnectivityOrientationInfo(); return cb; } @Override public void pushTexture(LDrawTextureSpec tex_spec) { // TODO Auto-generated method stub } @Override public void popTexture() { // TODO Auto-generated method stub } @Override public void drawQuad(float[] vertices, float[] normal, float[] color) { for (int i = 0; i < vertices.length; i += 3) { quad.add(new Vector3f(vertices[i], vertices[i + 1], vertices[i + 2])); } } @Override public void drawTri(float[] vertices, float[] normal, float[] color) { for (int i = 0; i < vertices.length; i += 3) { tri.add(new Vector3f(vertices[i], vertices[i + 1], vertices[i + 2])); } } @Override public void drawLine(float[] vertices, float[] normal, float[] color) { // TODO Auto-generated method stub } }